import axios, { AxiosInstance } from 'axios'
import { ElMessage, ElMessageBox } from 'element-plus'
import classToken from '../utils/auth'

const pendingRequest = new Map()

function generateReqKey(config: any) {
  const { method, url, params, data } = config
  return [method, url, JSON.stringify(params), JSON.stringify(data)].join('&')
}

function addPendingRequest(config: any) {
  const requestKey = generateReqKey(config)
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {
      if (!pendingRequest.has(requestKey)) {
        pendingRequest.set(requestKey, cancel)
      }
    })
}

function removePendingRequest(config: any) {
  const requestKey = generateReqKey(config)
  if (pendingRequest.has(requestKey)) {
    const cancel = pendingRequest.get(requestKey)
    cancel(requestKey)
    pendingRequest.delete(requestKey)
  }
}

const service: AxiosInstance = axios.create({
  baseURL: import.meta.env.VITE_BASE_API, // api
  timeout: 5000,
  headers: {
    'Content-Type': 'application/json; charset=utf-8'
  }
})

// Request interceptors
service.interceptors.request.use(
  (config) => {
    // 请求头中添加token
    if (classToken.getToken()) {
      config.headers.token = classToken.getToken()
    }
    removePendingRequest(config) // 检查是否存在重复请求，若存在则取消已发的请求
    addPendingRequest(config) // 把当前请求添加到pendingRequest对象中
    return config
  },
  (error) => {
    Promise.reject(error)
  }
)

// Response interceptors
service.interceptors.response.use(
  (response) => {
    removePendingRequest(response.config) // 从pendingRequest对象中移除请求
    const res: any = response.data
    if (res.code !== 200) {
      ElMessage.error(res.message)
      // token失效，退出登录
      if (res.code === 401) {
        ElMessageBox.confirm('登录失效，是否确认重新登录？', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          location.reload()
        })
      }
      return Promise.reject(response.data)
    } else {
      return response.data
    }
  },
  (error) => {
    removePendingRequest(error.config || {}) // 从pendingRequest对象中移除请求
    if (axios.isCancel(error)) {
      console.log('已取消的重复请求：' + error.message)
    } else {
      // 添加异常处理
      ElMessage.error(error.message)
    }
    return Promise.reject(error)
  }
)

export default service
